﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Wisdom.Core;

namespace Wisdom.Web.Mvc
{
    /// <summary>
    /// Defines a class which is used to register the default <seealso cref="ModelMetadataProvider"/>.
    /// </summary>
    public class RegisterModelMetadata : BootstrapperTask
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="RegisterModelMetadata"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        public RegisterModelMetadata(IObjectContainer container)
        {
            Guard.IsNotNull(container, "container");

            Container = container;
        }

        /// <summary>
        /// Gets the container.
        /// </summary>
        /// <value>The container.</value>
        protected IObjectContainer Container
        {
            get;
            private set;
        }

        /// <summary>
        /// Executes the task. Returns continuation of the next task(s) in the chain.
        /// </summary>
        /// <returns></returns>
        public override TaskContinuation Execute()
        {
            IEnumerable<Type> concreteTypes = Container.GetService<IBuildManager>().ConcreteTypes;

            concreteTypes.Where(type => KnownTypes.ModelMetadataConfigurationType.IsAssignableFrom(type))
                         .Each(type => Container.RegisterAsTransient(KnownTypes.ModelMetadataConfigurationType, type));

            IEnumerable<IModelMetadataConfiguration> configurations = Container.GetServices<IModelMetadataConfiguration>();

            var registry = Container.GetService<IModelMetadataRegistry>();

            configurations.Each(configuration => registry.RegisterModelProperties(configuration.ModelType, configuration.Configurations));

            IList<ModelValidatorProvider> validatorProviders = new List<ModelValidatorProvider>(ModelValidatorProviders.Providers);
            validatorProviders.Insert(0, new ExtendedModelValidatorProvider());
            var compositeModelValidatorProvider = new CompositeModelValidatorProvider(validatorProviders.ToArray());

            ModelMetadataProviders.Current = new ExtendedModelMetadataProvider(registry);
            ModelValidatorProviders.Providers.Clear();
            ModelValidatorProviders.Providers.Add(compositeModelValidatorProvider);

            return TaskContinuation.Continue;
        }
    }
}